package de.connecttext.services;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import de.connecttext.application.Constants;
import de.connecttext.dao.solr.WikipediaSolrDao;
import de.connecttext.model.TagVector;

/**
 * Decides, which Tags of the Document are relevant to its topic. Roughly, this
 * is based on the respective tf_idf value. More detailed explanations in the
 * comments
 * 
 * @author conrad
 * 
 */
public class TagSelectAndRefiner {

	private static TagSelectAndRefiner instance;
	private WikipediaSolrDao solrDao;

	public TagSelectAndRefiner() {
		this.solrDao = WikipediaSolrDao.getInstance();
	}

	public List<TagVector> selectAndRefineTags(String solrId,
			List<TagVector> tagVectors) throws IOException {

		
		tagVectors = selectTags(tagVectors);
		
		tagVectors = refineTags(solrId, tagVectors);
		return tagVectors;
	}

	/**
	 * Queries the solrDao to retrieve the OriginalTermn for each TagVector
	 * 
	 * @param solrId
	 * @param tagVectors
	 * @return
	 * @throws IOException
	 */
	private List<TagVector> refineTags(String solrId, List<TagVector> tagVectors)
			throws IOException {
		for (TagVector tagVector : tagVectors) {
			tagVector.setOriginalTerm(solrDao.retrieveOriginalTerm(solrId,
					tagVector.getLemmatizedTerm()));
		}
		return tagVectors;
	}

	/**
	 * Chooses the Tags with the highest tfidf for the document, within given
	 * range by constants
	 * 
	 * @param tagVectors
	 * @return
	 */
	private List<TagVector> selectTags(List<TagVector> tagVectors) {

		if (tagVectors.size() < Constants.MINIMAL_TAGS_THRESHOLD)
			return tagVectors;

		List<TagVector> bufferedVectors = new ArrayList<TagVector>();

		// Get the tagVectors with the highest tfidf in front
		Collections.sort(tagVectors);
		if (tagVectors.get(0).getTfidf() < tagVectors.get(1).getTfidf())
			Collections.reverse(tagVectors);

		/*
		 * // Add every Tag to the List until MINIMAL_TAGS_THRESHOLD is //
		 * reached int lowerThreshold = Math.min(tagVectors.size(),
		 * Constants.MINIMAL_TAGS_THRESHOLD);
		 * 
		 * for (int i = 0; i < lowerThreshold; i++) {
		 * 
		 * bufferedVectors.add(tagVectors.get(i));
		 * 
		 * }
		 */

		// Add the Rest of the Tags to the List if theyre tfidf is greater than
		// MINIMAL_TFIDF_TRESHOLD, until MAXIMAL_TAGS_THRESHOLD is
		// reached

		int upperThreshold = Math.min(tagVectors.size(),
				Constants.MAXIMAL_TAGS_THRESHOLD);

		for (int i = 0; i < upperThreshold; i++) {

			TagVector tagVector = tagVectors.get(i);
			if (tagVector.getTfidf() < Constants.MINIMAL_TFIDF_TRESHOLD)
				break;
			// The shingleFilter applies underscores to filtered Tokens, we dont
			// want that
			if (tagVector.getLemmatizedTerm().indexOf("_") == -1)
				bufferedVectors.add(tagVectors.get(i));
			else {
				// If the Term has an underscore, we take on more term from the
				// Tagvectors, since the MAXIMAL_TAGS_THRESHOLD cant be reached
				// if not
				if (upperThreshold + 1 > tagVectors.size()) {
					upperThreshold++;
				}
			}
		}

		return bufferedVectors;
		/*
		 * // Check if the MinimalTagsTheshold-th tagVector's tfidf is greater
		 * than // the MinimalTdfidfThreshold, add more Tags, else if
		 * (tagVectors.get(Constants.MINIMAL_TAGS_THRESHOLD - 1).getTfidf() >
		 * Constants.MINIMAL_TFIDF_TRESHOLD) {
		 * 
		 * }
		 * 
		 * // All Tags are now buffered in bufferedVectors, so this List is to
		 * be // cleared, then filled again tagVectors.clear();
		 * 
		 * Collections.sort(bufferedVectors);
		 * Collections.reverse(bufferedVectors);
		 * 
		 * // If the Tfidf - value is too low, throw the tag away for (TagVector
		 * bufferedVector : bufferedVectors) { if (bufferedVector.getTfidf() >
		 * Constants.MINIMAL_TFIDF_TRESHOLD) tagVectors.add(bufferedVector); }
		 * 
		 * // If there are enough Tags and not too many, return if
		 * (tagVectors.size() >= Constants.MINIMAL_TAGS_THRESHOLD &&
		 * tagVectors.size() <= Constants.MAXIMAL_TAGS_THRESHOLD) return
		 * tagVectors;
		 * 
		 * // If too many, cut the rest and return if (tagVectors.size() >
		 * Constants.MAXIMAL_TAGS_THRESHOLD) { Collections.sort(tagVectors);
		 * return tagVectors.subList(0, Constants.MAXIMAL_TAGS_THRESHOLD - 1); }
		 * 
		 * /* // If there arent enough, The Tags with the highest Tf Value are
		 * added to the list // First: // Sort by Tf value
		 * Collections.sort(bufferedVectors, new Comparator<TagVector>() {
		 * 
		 * @Override public int compare(TagVector tagVector1, TagVector
		 * tagVector2) { if (tagVector1.getTf() < tagVector2.getTf()) return -1;
		 * if (tagVector1.getTf() > tagVector2.getTf()) return 1; return 0; }
		 * 
		 * }); // The highest value at the beginning of the list //
		 * Collections.reverse(bufferedVectors);
		 * 
		 * // Add all TagVectors ordered by the tf value to the list until the
		 * // minimal threshold is reached for (TagVector bufferedVector :
		 * bufferedVectors) { if (tagVectors.size() >
		 * Constants.MINIMAL_TAGS_THRESHOLD) break; if
		 * (!tagVectors.contains(bufferedVector) && bufferedVector.getTf() > 1 )
		 * tagVectors.add(bufferedVector); }
		 */

		// return tagVectors;

	}

}
